home *** CD-ROM | disk | FTP | other *** search
- /*
- * BBSindex (C) Copyright Eddy Carroll, August 1989
- *
- * This is a utility which will scan the file catalogue of BBS-PC! and
- * build lists of the files in various sections and directories.
- *
- * It is designed to be run automatically on a regular basis in the
- * background. It reads in instructions from an input file, and
- * produces output files based on these instructions.
- *
- * Usage: BBSindex [options] [scriptfile] ..
- *
- * With no parameters, a short help message is displayed.
- *
- * The possible options are:
- *
- * -c <file> This specifies the configuration file (CFGINFO.DAT)
- * -d <file> This specifies the input file (default UDHEAD.DAT)
- * -f "string" This specifies the format string for the output
- * -h Displays the help message
- * -n Stops AmigaDOS putting up requesters
- * -t Trace mode - display each line before execution
- *
- * scriptfile is a file containing commands to control what is output.
- * See the documentation for more info. Note that options and script files
- * may be freely interspersed.
- *
- */
-
- #define MAIN
-
- #ifndef LATTICE_50
- #include "system.h"
- #endif
-
- #include "bbsindex.h"
-
- /*
- * Miscellaneous static global variables
- */
-
- static struct IntuitionBase *IntuitionBase;
- static BPTR infile, lock;
- static struct Remember *memkey;
- static char buffer[BUFSIZE];
- static int bufpos = 0;
- static APTR requeststat; /* Ptr to window for AmigaDos requesters */
-
- /*
- * print()
- * -------
- * Prints a string to standard output
- */
- void print(s)
- char *s;
- {
- Write(errorfile,s,strlen(s));
- }
-
- /*
- * Cleanup()
- * ---------
- * Releases all program resources, and exits. Note that because of
- * the way it checks to see if a resource is allocated, you need to
- * set pointers to NULL if you release the object associated with
- * them. For example, when you close a file, remember to set the
- * file handle to NULL immediately afterwards, otherwise Cleanup()
- * will try to close it again.
- */
- void Cleanup(code)
- int code;
- {
- static ctrlc;
- struct Process *me = (struct Process *)FindTask(0L);
- int i;
-
- if (!ctrlc) {
- ctrlc = 1;
- me->pr_WindowPtr = requeststat;
- if (script)
- FreeMem(script, scriptsize);
- for (i = 0; i < nummacros; i++)
- FreeMem(macros[i], MACROSIZE + macros[i]->size);
- for (i = 0; i < nestlevel; i++)
- FreeMem(params[i], PARAMSIZE + params[i]->size);
- if (memkey)
- FreeRemember(&memkey, TRUE);
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- if (lock)
- UnLock(lock);
- if (dirlock)
- UnLock(dirlock);
- if (infile)
- Close(infile);
- if (outfile != Output())
- Close(outfile);
- if (errorfile)
- Close(errorfile);
- exit(code);
- }
- }
-
- /*
- * cxovf()
- * -------
- * The standard lattice "stack abort" code. This is called when the
- * stack overflows (having first reset the stack pointer to something
- * safe of course).
- */
- void cxovf()
- {
- print("\nBBSindex: Stack overflow! Use the STACK command "
- "to increase stack size\n");
- Cleanup(32);
- }
-
- /*
- * chkabort()
- * ----------
- * My own version of chkabort(), called by the Lattice Library
- * functions periodically to check for CTRL-C.
- *
- * This version cleans up first (otherwise, after CTRL-C'ing a few times
- * while processing a 220K UDHEAD.DAT file, you find you don't have any
- * memory left!).
- */
- void chkabort()
- {
- if (SetSignal(0,0) & SIGBREAKF_CTRL_C) {
- SetSignal(0,0xffffffff);
- print("^C\n");
- Cleanup(5);
- }
- }
-
-
- /*
- * SafeAllocMem()
- * --------------
- * A revised AllocMem() that checks for out of memory.
- */
- void *SafeAllocMem(size)
- int size;
- {
- void *ptr = AllocMem(size, 0);
- if (!ptr) {
- print("BBSindex: Out of memory!\n");
- Cleanup(20);
- }
- return (ptr);
- }
-
-
- /*
- * mymalloc()
- * ----------
- * My own private malloc. No memory limits, and no library overhead.
- * Easy to replace the call to AllocRemember with one to malloc for
- * portability. To try and keep down memory fragmentation, requests
- * for memory less than 200 bytes are allocated from a larger block
- * which is allocated "on the fly".
- */
- void *mymalloc(size)
- int size;
- {
- static void *bigblock; /* Current large memory block */
- static int curpos = FRAGBLOCK; /* Current position in block */
- void *ptr;
-
- size = (size + 7) & 0xfffffff8; /* Round up to 8 block boundary */
- if (size < FRAGTHRESH) {
- /*
- * If we want a small chunk, allocate it from our intermediate
- * block.
- */
- if ((size + curpos) > FRAGBLOCK) {
- bigblock = mymalloc(FRAGBLOCK);
- curpos = 0;
- }
- ptr = (char *)bigblock + curpos;
- curpos += size;
- } else {
- /*
- * Otherwise, just allocate memory as normal.
- */
- ptr = AllocRemember(&memkey, size, 0);
- if (!ptr) {
- print("BBSindex: Out of memory!\n");
- Cleanup(20);
- }
- }
- return (ptr);
- }
-
-
- /*
- * dumpdata()
- * ----------
- * Outputs raw data to a file, checking for write errors.
- */
- void dumpdata(buf,len)
- char *buf;
- int len;
- {
- if (Write(outfile, buf, len) != len) {
- print("BBSindex: Error writing output file (disk full?)\n");
- Cleanup(10);
- }
- }
-
- /*
- * putstring()
- * -----------
- * This function outputs a string to the current output file. If the
- * file is a tty, the string is output immediately, else it is
- * buffered up and output when it is big enough.
- */
-
- void putstring(s)
- char *s;
- {
- int len = strlen(s);
-
- if (toscreen) {
- dumpdata(s, len);
- } else {
- if ( (bufpos + len) > BUFSIZE) {
- dumpdata(buffer, bufpos);
- bufpos = 0;
- }
- strcpy(buffer+bufpos, s);
- bufpos += len;
- }
- }
-
- /*
- * flushout()
- * ----------
- * Flushes output to disk, before closing a file.
- */
-
- void flushout()
- {
- if (bufpos > 0) {
- dumpdata(buffer, bufpos);
- }
- bufpos = 0;
- }
-
- /*
- * openfile()
- * ----------
- * Opens a specified file for reading, and returns the length
- * of the file. If an error occurs, aborts automatically. The
- * caller has responsibility for calling Close(infile) when finished
- * with the file.
- */
- long openfile(filename)
- char *filename;
- {
- if ((lock = Lock(filename, ACCESS_READ)) == NULL) {
- print3("BBSindex: Can't access file ",filename,"\n");
- Cleanup(5);
- }
-
- if (!Examine(lock, fib)) {
- print3("BBSindex: Can't get info for file ",filename,"\n");
- Cleanup(5);
- }
- UnLock(lock); lock = NULL;
-
- if ((infile = Open(filename, MODE_OLDFILE)) == NULL) {
- print3("BBSindex: Can't open file ",filename," for input\n");
- Cleanup(5);
- }
- return (fib->fib_Size);
- }
-
- /*
- * readdatabase()
- * --------------
- * This function reads in the entire file database into memory,
- * allocating memory as required. It sets up an array of pointers to
- * the records in the database, which is used by qsort() among other
- * things.
- *
- * Note that the memory needed is allocated in a number of small
- * chunks each BLOCKSIZE * UDSIZE bytes in size (~16K by default).
- * This means there doesn't need to be a contigous block of memory
- * big enough to hold the whole file database available - it is
- * split into smaller chunks instead.
- */
-
- void readdatabase(filename)
- char *filename;
- {
- long size;
- long bsize;
- long i,j;
- UDHEAD *block; /* Pointer to block of headers */
- UDHEAD **p;
-
- readfiles = TRUE;
-
- size = openfile(filename);
- if ((size % UDSIZE) || (size < (2 * UDSIZE))) {
- print3("BBSindex: ",filename,
- " isn't a valid BBS-PC! file header file!\n");
- Cleanup(5);
- }
-
- /*
- * File successfully opened, now read in file data.
- * Skip past unneeded data at start of BBS-PC! file
- */
- Seek(infile, UDSIZE * 2, OFFSET_BEGINNING);
- size = size - (2 * UDSIZE);
- numrecs = size/UDSIZE;
- ptrblock = mymalloc(numrecs * sizeof(UDHEAD *));
- p = ptrblock;
-
- /*
- * Now allocate blocks to hold data, read in data, and setup initial
- * pointers to point to the file headers.
- */
- for (i = numrecs; i > 0; i = i - BLOCKSIZE) {
-
- bsize = (i > BLOCKSIZE ? BLOCKSIZE : i);
- block = mymalloc(bsize * UDSIZE);
-
- chkabort();
- if (Read(infile, block, bsize * UDSIZE) != (bsize * UDSIZE)) {
- print3("BBSindex: Error reading from file",filename,"\n");
- Cleanup(10);
- }
-
- /*
- * Now initialise all the pointers for this block. Also
- * null-terminate the catalogue filename, since BBS-PC!
- * doesn't always save out the null termination byte.
- * Also set Online and Valid files to 0, by default.
- * These will be updated by CHECKFILES.
- */
-
- for (j = 0; j < bsize; j++) {
- block->cat_name[15] = '\0';
- block->online = 0;
- block->valid = 0;
- block->dirnum = 0;
-